
#include "precomp.h"
#include "Kernel.h"
#include "Scene/cache_provider.h"

using namespace RL;
using namespace Engine;

using namespace clan;

Kernel::Kernel()
	: _isSetUp(false), _isRunning(false)
{
}

Kernel::~Kernel()
{
}

bool Kernel::setup(int width, int height, const std::string &title, bool fullscreen)
{
	if(_isSetUp || _isRunning || _window.is_null())
		return false;

	try
	{
		_window = DisplayWindow(title, width, height, fullscreen, true);
		GraphicContext gc = _window.get_gc();

		_loadResources();
		
		_cache = SceneCache(new RLSceneCacheProvider());

		auto shader = _resources->get_resource("shaders");
		auto shader_dir = _resources->get_directory(shader);
		
		_scene = Scene(gc, _cache, );
	}
	catch(Exception &e)
	{
		ConsoleWindow console("Console", 80, 160);
		Console::write_line("Exception caught: " + e.get_message_and_stack_trace());
		console.display_close_message();
		return false;
	}
	
	_isSetUp = true;
	return true;
}

void Kernel::run()
{
	if(_isSetUp == false || _isRunning || _display == nullptr)
		return;

	auto canvas = _display->getCanvas();
	auto window = canvas.get_window();
	window.show();
	auto closeSlot = window.sig_window_close().connect(this, &Kernel::stop);
	auto inputContext = window.get_ic();

	_isRunning = true;
	while(_isRunning)
	{
		if(inputContext.get_keyboard().get_keycode(keycode_escape))
			stop();

		canvas.clear();

		canvas.draw_box(10.0f, 10.0f, 90.0f, 90.0f, clan::Colorf(1.0f, 0.0f, 0.0f));

		canvas.flip(1);
		KeepAlive::process();
	}

	window.hide();
}

void Kernel::stop()
{
	_isRunning = false;
}

void Kernel::_setupClanLib()
{
	srand(System::get_time());
}

void Kernel::_loadResources()
{
	auto path = System::get_exe_path();
	auto root_path = path.substr(0, path.find("Bin"));
	clan::VirtualFileSystem vfs(root_path);
	clan::VirtualDirectory vd(vfs, "Resources");
	_resources = new clan::ResourceManager(vd.open_file("resources.xml"), vd);
	
	_addResourcesInDirectory(*_resources, vd, "Fonts");
}

void Kernel::_setupDisplay(const std::string &title)
{
	_display = new Engine::Display(title);
}

void Kernel::_addResourcesInDirectory(clan::ResourceManager &resources, clan::VirtualDirectory &vd, const std::string &directory)
{
	auto dir = vd.open_directory(directory);
	auto dir_list = dir.get_directory_listing();
	while(!dir_list.is_null())
	{
		auto file = dir_list.get_filename();
		if(file.find(".xml") == std::string::npos)
		{
			if( dir_list.next() == false )
				break;
			else
				continue;
		}

		resources.add_resources(clan::ResourceManager(dir.open_file(file), dir));

		if( dir_list.next() == false )
			break;
	}
}
